#include "GridMap.h"

#include <SFML/Graphics.hpp>

#include <string>

#include "../GlobalConsts.h"

GridMap::GridMap () : baseLayer (),
					  miscLayer (),
					  vertices (),
					  mapTexture (nullptr)
{
}

GridMap& GridMap::getInstance ()
{
	static GridMap instance;
	return instance;
}

void GridMap::loadMap (std::ifstream& ifstream, Image::TileTexture tileTexture)
{
	//TODO: The tileset should be set somewhere else.
	mapTexture = ImageCache::getInstance ().getTileTexture (tileTexture);

	std::string line;
	if (ifstream.is_open ()) {
		while (std::getline (ifstream, line)) {
			baseLayer.push_back (std::vector<int> ());

			//TODO: This solution is limited to 1 digit numbers, good enough yet
			for (std::size_t i = 0; i < line.size (); i += 2) {
				baseLayer[baseLayer.size () - 1].push_back (atoi (&line[i]));
			}
		}
		ifstream.close ();
	}

    vertices.setPrimitiveType(sf::Quads);
    vertices.resize(baseLayer.size () * baseLayer[0].size () * 4);

    for (unsigned int i = 0; i < baseLayer.size (); ++i)
        for (unsigned int j = 0; j < baseLayer[0].size (); ++j)
        {
            int tileNumber = baseLayer[i][j];

            // find its position in the tileset texture
            int tu = tileNumber % (mapTexture->getSize().x / baseLayer.size ());
            int tv = tileNumber / (mapTexture->getSize().x / baseLayer.size ());

            sf::Vertex* quad = &vertices[(i + j * baseLayer.size ()) * 4];

            quad[0].position = sf::Vector2f (static_cast<float> (j * Tile_Width), static_cast<float> (i * Tile_Height));
            quad[1].position = sf::Vector2f (static_cast<float> ((j + 1) * Tile_Width), static_cast<float> (i * Tile_Height));
            quad[2].position = sf::Vector2f (static_cast<float> ((j + 1) * Tile_Width), static_cast<float> ((i + 1) * Tile_Height));
            quad[3].position = sf::Vector2f (static_cast<float> (j * Tile_Width), static_cast<float> ((i + 1) * Tile_Height));

            quad[0].texCoords = sf::Vector2f(static_cast<float> (tu * Tile_Width), static_cast<float> (tv * Tile_Height));
            quad[1].texCoords = sf::Vector2f(static_cast<float> ((tu + 1) * Tile_Width), static_cast<float> (tv * Tile_Height));
            quad[2].texCoords = sf::Vector2f(static_cast<float> ((tu + 1) * Tile_Width), static_cast<float> ((tv + 1) * Tile_Height));
            quad[3].texCoords = sf::Vector2f(static_cast<float> (tu * Tile_Width), static_cast<float> ((tv + 1) * Tile_Height));
        }

}

const std::vector<std::vector<int>>& GridMap::getBaseLayer () const
{
	return baseLayer;
}

const std::vector<std::vector<int>>& GridMap::getMiscLayer () const
{
	return miscLayer;
}

bool GridMap::processLeftClickEvent (const sf::Vector2i& pos) const
{
 	/*if (TODO: RangeCheck)
		return true;*/
    return false;
}

bool GridMap::processRightClickEvent (const sf::Vector2i& pos) const
{
	/*if (TODO: RangeCheck)
		return true;*/
    return false;
}

void GridMap::draw (sf::RenderTarget& target, sf::RenderStates states) const
{
        states.transform *= getTransform ();
		
        states.texture = mapTexture;

        target.draw(vertices, states);
}